/*
 * @Description: axios封装
 * @Author: chenju
 * @Date: 2021-01-05 16:08:55
 * @LastEditors: qingyang
 * @LastEditTime: 2023-06-20 16:21:11
 */

import axios from 'axios';
import { HTTP_RESPONSE_CODE } from '@/constants';
import constants from '@/constants';
import config from '@/config';
import { store } from '@/store/index';
import { UserActionTypes } from '@/store/modules/user/action-types';
import { comparisonVersion, showMessage } from './http.utils';
declare const window: any;
import { useMessage } from '@/hooks/useMessage';
const { createMessage } = useMessage();

/**
 * 取消未完成请求，在需停止上一请求时手工调用（如弹层关闭时）
 */
export function cancelRequest() {
  const source = window.currentSource;
  console.log('手工取消', source);
  source && source.cancel && source.cancel('用户取消操作');
  /* 刷新source */
  window.currentSource = axios.CancelToken.source();
}

/**
 * 处理401及没有刷新token失败的情况
 */
function handleNoAuthAndGotoLogin() {
  console.log('处理401及没有刷新token失败的情况');
  // 仅在第一次登出时弹出错误提示
  if (store.state.user.isLogin === true) {
    createMessage.error(constants.RESPONSE_ERROR.get('TOKEN_EXPIRED') as string);
  }
  // 前端登出
  store.dispatch(UserActionTypes.ACTION_LOGIN_OUT);
}

const $http: any = axios.create();

// post请求头设置
$http.defaults.headers.post['Content-Type'] = 'application/json';
$http.defaults.headers.put['Content-Type'] = 'application/json';
// 请求域名
$http.defaults.baseURL = config.BASE_URL;
// 超时时间
$http.defaults.timeout = config.TIMEOUT;
// 用于取消请求
window.currentSource = {};

// request 拦截
$http.interceptors.request.use(
  async (config: any) => {
    console.log('request interceptor', config);
    if (config && config.noAuth) {
      return config;
    } else {
      try {
        const token = await store.dispatch(UserActionTypes.ACTION_GET_ACCESS_TOKEN);
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        // 用于取消请求
        if (!window.currentSource) {
          window.currentSource = axios.CancelToken.source();
        }
        config.cancelToken = window.currentSource && window.currentSource.token;
        return config;
      } catch (err: any) {
        console.log(
          'request interceptor 获取token异常',
          err.message,
          localStorage.getItem('token')
        );
        if (localStorage.getItem('token')) {
          handleNoAuthAndGotoLogin();
          return Promise.reject(err);
        } else {
          console.log('401 请求拦截器 已经退出');
          return Promise.reject(new Error('已经退出'));
        }
      }
    }
  },
  (error: any) => {
    console.log('request error', error);
    return Promise.reject(error);
  }
);

// response 拦截
$http.interceptors.response.use(
  (response: any) => {
    console.log('response', response);
    // 校验版本号 后端版本较高时会刷新页面
    const version = response.headers['footprint-version'];
    comparisonVersion(version);

    const { code, data, msg } = response.data;
    // 如果是文件流直接返回
    if (response.request && response.request.responseType == 'blob') {
      return response;
    }
    if (code && code === HTTP_RESPONSE_CODE.OK_CODE) {
      return data;
    } else {
      response.config.showMessage &&
        createMessage.error(msg || constants.RESPONSE_ERROR.get('ABNORMAL_ERROR'));
      return Promise.reject(response);
    }
  },
  (error: any) => {
    console.log('response error', error, error.message, error.response);
    const { message: errorMsg, response } = error;
    if (errorMsg === '已经退出') {
      return Promise.reject(error);
    } else if (errorMsg === 'Network Error') {
      createMessage.error(constants.RESPONSE_ERROR.get('NETWORK_ERROR') as string);
      return Promise.reject(error);
    } else if (errorMsg.includes('timeout')) {
      createMessage.error(constants.RESPONSE_ERROR.get('TIME_OUT') as string);
    } else if (errorMsg === '用户取消操作') {
      response.config.showMessage &&
        createMessage.error(constants.RESPONSE_ERROR.get('REQUEST_CANCEL') as string);
    } else if (response && response.status === 400) {
      response.config.showMessage &&
        createMessage.error(
          response.data.msg || (constants.RESPONSE_ERROR.get('ERROR_400') as string)
        );
      return Promise.reject(error);
    } else if (response && response.status === 401) {
      handleNoAuthAndGotoLogin();
      return Promise.reject(error);
    } else if (response && response.status === 404) {
      response.config.showMessage &&
        createMessage.error(
          response.data.msg || (constants.RESPONSE_ERROR.get('ERROR_404') as string)
        );
      return Promise.reject(error);
    } else if (response && response.status === 500) {
      response.config.showMessage &&
        createMessage.error(
          response.data.msg || (constants.RESPONSE_ERROR.get('ERROR_500') as string)
        );
      return Promise.reject(error);
    } else if (response && response.status === 503) {
      response.config.showMessage &&
        createMessage.error(constants.RESPONSE_ERROR.get('ERROR_503') as string);
      return Promise.reject(error);
    } else {
      if (response.data.msg || errorMsg) {
        response.config.showMessage && createMessage.error(response.data.msg || errorMsg);
      }
      return Promise.reject(error);
    }
  }
);

export const baseURL = $http.defaults.baseURL;

export const get = (url: string, params?: any, noAuth = false, showMessage = true) => {
  return $http({
    method: 'get',
    url: url,
    params,
    noAuth,
    showMessage
  });
};

export const post = (url: string, params?: any, noAuth = false, showMessage = true) => {
  return $http({
    method: 'post',
    url: url,
    data: params,
    noAuth,
    showMessage
  });
};

// post请求通过url传递参数
export const postByUrl = (url: string, params?: any, noAuth = false, showMessage = true) => {
  return $http({
    method: 'post',
    url: url,
    params,
    noAuth,
    showMessage
  });
};

// get文件流
export const getBlob = (url: string, params?: any, noAuth = false, showMessage = false) => {
  return $http({
    method: 'get',
    url: url,
    params,
    responseType: 'blob',
    noAuth,
    showMessage
  });
};

// post获取文件流
export const postBlob = (url: string, params?: any, noAuth = false, showMessage = false) => {
  return $http({
    method: 'post',
    url: url,
    data: params,
    responseType: 'blob',
    noAuth,
    showMessage
  });
};
export const postParams = (
  url: string,
  data?: any,
  params?: any,
  noAuth = false,
  showMessage = true
) => {
  return $http({
    method: 'post',
    url: url,
    data,
    params,
    noAuth,
    showMessage
  });
};
